#pragma once
#include "ServerHook.h"
#include "lua.hpp"
#include "cJSON.h"
#include "Config.h"
#include <map>
#include <list>

class LuaHookProtocol;

class LuaAccepter :public BaseAccepter {
public:
	lua_State* L = NULL;
	LuaHookProtocol* proto = NULL;
	std::list<HSOCKET> listen_list;
	LuaAccepter(void(*accepted)(BaseAccepter*, HSOCKET)) { this->accepted = accepted; };
	~LuaAccepter() {};
	BaseWorker* GetWorker() { return NULL; };
};

class LuaHookProtocol :
	public ServerHookProtocol
{
public:
	time_t time_last_gc = 0;
	lua_State* GL = NULL;
	
	std::list<lua_State*>		TLS;		//空闲的lua thread
	std::map<lua_State*, int>	TL_REF;		//lua虚拟机持有lua thread的引用，防止被lua虚拟机gc
	std::map<void*, int>		HandleRef;  //开打的timer 0、socket 1、accepter 2
	std::map<void*, int>		ProxyRef;

	std::map<std::string, bool> OldVmPackageLoaded;
	std::map<std::string, bool> OldVmGlobalLoaded;
public:
	LuaHookProtocol();
	LuaHookProtocol(LuaHookProtocol* ppid);
	~LuaHookProtocol();

	void ConnectionAccepted(LuaAccepter* accepter, HSOCKET hsock, PROTOCOL protocol);
	void ConnectionMade(HSOCKET hsock, PROTOCOL protocol);
	void ConnectionFailed(HSOCKET hsock, int err);
	void ConnectionClosed(HSOCKET hsock, int err);
	void ConnectionRecved(HSOCKET hsock, const char* data, int len);

	void RunScript(const char* script);

	//void RunTask(const char* script, const char* fun, Task_Content* task_ctx);
	//void TaskPulled(Task_Content* task_ctx, Task_Message* message);

	void init();
	void reinit();
	void timer_out();
	void time_sleep(HTIMER timer);
	void http_handler(HSOCKET hsock, const char* data, int len);
	void event_handler(cJSON* root);
	void event_task(ServerTaskConfig* taskcfg, const char* event);
	void event_agent(t_sheeps_agent* agent, const char* event);

	void proxy_connect_open_hook(const char* proxy_type, const char* host, HSOCKET from, HSOCKET to, PROTOCOL protocol);
	void proxy_connect_faile_hook(const char* proxy_type, const char* host, HSOCKET from, HSOCKET to, PROTOCOL protocol);
	void proxy_connect_close_hook(const char* proxy_type, HSOCKET from, HSOCKET to, PROTOCOL protocol);
	int proxy_connect_send_hook(const char* proxy_type, HSOCKET from, HSOCKET to, PROTOCOL protocol, const char* data, int len);
	int proxy_connect_recv_hook(const char* proxy_type, HSOCKET from, HSOCKET to, PROTOCOL protocol, const char* data, int len);
};

#define LUA_HOOK_PROTOCOL_SIZE sizeof(LuaHookProtocol)

int sheeps_report(lua_State* L, int status, LuaHookProtocol* proto, const char* func, int line);
void reback_thread_state(LuaHookProtocol* proto, lua_State* L);